package com.example.myapplication.kotlin

import java.io.File

/**
 * @author: rongfeng
 * @date: 2021/10/22
 * @description
 */
class Basic {

    val one = 1
    val threeBillion = 300000000
    val oneLong = 1L
    val oneByte: Byte = 1
    val oneMillion = 1_000_000
    val creditCardNumber = 1234_5678_9012_3456L
    val socialSecurityNumber = 999_999_9999L
    val hexBytes = 0xFF_EC_DE_5E
    val bytes = 0b11011010_01101001


    fun sum(a: Int, b: Int): Int {
        return a + b;
    }

    fun sum2(a: Int, b: Int) = a + b


    fun printSum(a: Int, b: Int): Unit {
        println("sum of $a and $b is {a+b}")
    }

    fun variables() {
        val a: Int = 1
        val b = 2
        val c: Int

        var x = 5
        x = x + 1
    }

    val PI = 2.13
    var x = 1
    fun incrementX() {
        x += 2
        print(x)
    }

    class Shape

    class Rectangle(var height: Double, var lenght: Double) {
        var perimeter = (height + lenght) * 2
    }

    open class Shape2

    class Rectangle2(var height: Double, val length: Double) : Shape2() {
        var perimeter = (height + length) * 2
    }

    var a = 1
    val s1 = "a is $a"
    var s2 = "${s1.replace("is", "was")},but no is $a"
    fun maxOf(a: Int, b: Int): Int {
        if (a > b) {
            return a
        } else {
            return b
        }
    }

    fun maxOf2(a: Int, b: Int) = if (a > b) a else b

    val items = listOf("apple", "banana", "kiwifruit")

    fun forLoop() {
        for (item in items) {
            print(item)
        }
        for (index in items.indices) {
            println("item at $index is ${items[index]}")
        }
        var index = 0
        while (index < items.size) {
            println("item at $index is ${items[index]}")
            index++
        }
    }

    fun describe(obj: Any): String = when (obj) {
        1 -> "One"
        "hello" -> "Greeting"
        is Long -> "Long"
        !is String -> "Not a string"
        else -> "Unknown"
    }

    fun Ranges() {
        val x = 10
        val y = 9
        if (x in 1..y + 1) {
            println("fits in range")
        }

        val list = listOf("a", "b", "c")
        if (-1 !in 0..list.lastIndex) {
            println("-1 is our of range")
        }
        if (list.size !in list.indices) {
            println("list size is out of valid list indices range,too")
        }

        for (x in 1..5) {
            println(x)
        }

        for (x in 1..10 step 2) {
            println(x)
        }

        for (x in 9 downTo 0 step 3) {
            print(x)
        }
    }

    fun collections() {
        val items = listOf("apple", "banana", "kiwifruit")
        for (item in items) {
            println(item)
        }

        when {
            "orange" in items -> println("juicy")
            "apple" in items -> println("apple is fine too")
        }

        when (x) {
            0, 1 -> println()
            else -> println()
        }

        when (x) {
            in 1..10 -> println()
            !in 10..20 -> println()
        }

        val fruits = listOf("banana", "avocado", "apple", "kiwifruit")
        fruits.filter { it.startsWith("a") }
//                .sortedBy { it }
//                .map { it.toUpperCase() }
//                .forEach(println(it))
    }

    fun nullable() {

    }

    fun parseInt(str: String): Int? {
        return str.toIntOrNull()
    }

    fun printProduct(arg1: String, arg2: String) {
        val x = parseInt(arg1)
        val y = parseInt(arg2)
        if (x != null && y != null) {
            println(x * y)
        } else {
            println("'$arg1' or '$arg2' is not a number ")
        }

        if (x == null) {
            println("Wrong number format in arg1: '$arg1'")
            return
        }
        if (y == null) {
            println("wrong number format arg2: '$arg2'")
            return
        }

        println(x * y)
    }


    fun getStringLength(obj: Any): Int? {
        if (obj is String) {
            return obj.length
        }
        return null
    }

    fun getStringLength2(obj: Any): Int? {
        if (obj !is String) return null
        return obj.length
    }

    enum class Color {
        RED, GREEN
    }

    val elementList = mutableListOf<Any>()


    val isEmpty: Boolean get() = 1 == 0


    fun numbers() {
        val a: Int = 100
        val boxedA: Int? = a
        val anotherBoxedA: Int? = a

        val b: Int = 10000
        val boxedB: Int? = b
        val anotherBoxedB: Int? = b

        println(boxedA == anotherBoxedA)
        println(boxedA === anotherBoxedA)

        println(boxedB == anotherBoxedB)
        println(boxedB === anotherBoxedB)

        val c: Int = 1
        val d: Long = c.toLong()
        val l = 1L + 3
    }

    fun arithmetical() {
        val x = 5 / 2
        println(x)

        val y = 5L / 2
        println(y)

        val z = 5 / 2.toFloat()
        println(z)

        val aChar: Char = '2'
        println(aChar)

        println(aChar.isDigit())
    }

    fun strings() {
        var str = "abcd 123"
        for (c in str) {
            println(c)
        }

        str = "abcd"
        println(str.toUpperCase())

        str = "abc" + 1
        println(str + "def")

        //原始字符串由三重引号 ( """)分隔，不包含转义，并且可以包含换行符和任何其他字符：
        str = """for(c in "foo")print(c)"""

        println(str)

        // 默认情况下，|用作边距前缀，但您可以选择另一个字符并将其作为参数传递，例如trimMargin(">").
        str = """
                |Tell me and I forget.
                |Teach me and I remember.
                |Involve me and I learn.
                |(Benjamin Franklin)
                """.trimMargin()

        println(str)

        val i = 10
        println("i = $i")
        println("i = ${i}a")

        val s = "abc"
        println("$s.length is ${s.length}")

        val price = """${'$'}_9.99"""
        println(price)

    }


    fun array() {
        val x: IntArray = intArrayOf(1, 2, 3)
        for (x in 1..10 step 2) {
            println(x)
        }


        x[0] = x[1] + x[2]
        for (n in x) {
            println(n)
        }

        val aar = IntArray(5)
        val arr2 = IntArray(5) { 42 }
        val arr3 = IntArray(5) { it }


        for (n in arr3) {
            println(n)
        }

    }

    fun iss(x: Any, list: List<String>) {
        when (x) {
            is Int -> print(x + 1)
            is String -> print(x.length + 1)
            is IntArray -> print(x.sum())
        }
        if (x is List<*>) {

        }

        //相同的语法但省略了类型参数可用于不考虑类型参数的强制转换：list as ArrayList.
        if (list is ArrayList) {

        }

    }

    //reified关键字是用于Kotlin内联函数的,修饰内联函数的泛型,泛型被修饰后,在方法体里,能从泛型拿到泛型的Class对象,
    inline fun <reified A, reified B> Pair<*, *>.asPairOf(): Pair<A, B>? {
        if (first !is A || second !is B) return null
        return first as A to second as B
    }

    fun ass(obj: Any) {
        val y = null
        val x: String? = y as? String
        println(x)
    }

//    fun readDictionary(file: File):Map<String,*> = file.inputStream().use {
//
//    }

    fun fun1(callback: (number: Int) -> Unit) {
        callback.invoke(3)
    }

    fun hasPrefix(x: Any) = when (x) {
        is String -> x.startsWith("prefix")
        else -> false
    }


    fun map() {
        val map = mapOf("a" to 1, "b" to 2)

        for ((k, v) in map) {
            println("$k = $v")
        }

    }

    //单例
    object Resource {
        const val name = "张三"
    }

    fun let() {
        val value = "aaa"
        val mapped = value?.let {

        } ?: "bbbb"

    }

    @JvmOverloads
    fun test(a: Int, b: Int = 0, c: String = "") {
    }

    fun listDemo() {
        val list = listOf(1, 2)


        val arrayList = ArrayList<Int>()
        arrayList.add(1)
        arrayList.remove(0)

        val mutableList = mutableListOf<Int>()
        mutableList.add(1)
        mutableList.remove(0)

        val arraylistof = arrayListOf<Int>()
        arraylistof.add(1)


    }

    fun setTest(){


    }

    class SingletonDemo private constructor() {
        companion object {
            private var instance: SingletonDemo? = null
                get() {
                    if (field == null) {
                        field = SingletonDemo()
                    }
                    return field
                }
            fun get(): SingletonDemo{
                //细心的小伙伴肯定发现了，这里不用getInstance作为为方法名，是因为在伴生对象声明时，内部已有getInstance方法，所以只能取其他名字
                return instance!!
            }
        }
    }

    class Demo{
        val name = "haha"
    }

    companion object {
        @JvmStatic
        fun main(args: Array<String>) {
            val instance: Demo by lazy(mode = LazyThreadSafetyMode.SYNCHRONIZED) {
                Demo()
            }
            print(instance)
        }
    }

}